package com.zn
{
    import com.zn.loading.ImageLoader;
    import com.zn.loading.LoaderEvent;
    import com.zn.loading.LoaderItem;
    import com.zn.loading.LoaderMax;
    import com.zn.loading.LoaderStatus;
    import com.zn.loading.SWFLoader;
    import com.zn.loading.XMLLoader;
    import com.zn.loading.ZipLoader;
    import com.zn.utils.StringUtil;

    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.utils.Dictionary;

    import org.puremvc.as3.patterns.facade.Facade;

    /**
     * 资源加载
     * @author zn
     *
     */
    public class ResLoader
    {
        //显示加载条
        public static const SHOW_LOADER_BAR_NOTE:String = "showLoaderBarNote";

        //隐藏加载条
        public static const HIDE_LOADER_BAR_NOTE:String = "hideLoaderBarNote";

        //设置加载进度
        public static const SET_LOADER_BAR_PROGRESS_NOTE:String = "setLoaderBarProgressNote";

        //设置加载标题
        public static const SET_LOADER_BAR_TITLE_NOTE:String = "setLoaderBarTitleNote";

		public static const LOADER_ERROR_NOTE:String="loaderErrorNote";
		
        public static var faced:Facade;

        //回调方法缓存	key:name	value:array:function
        private static var _errorCallFunctionDic:Dictionary = new Dictionary();

        private static var _progressCallFunctionDic:Dictionary = new Dictionary();

        private static var _completeCallFunctionDic:Dictionary = new Dictionary();

        private static var _hasAddListenerDic:Dictionary = new Dictionary();

        private static var _showLoaderBarDic:Dictionary = new Dictionary();

        public function ResLoader()
        {
        }

        /**
         * 加载资源
         * @param loaderOrName
         * @param complete
         * @param flush 如果加载完成，是否重新加载
         * @param showLoaderBar 是否显示加载条
         * @param progress
         * @param error
         *
         */
        public static function load(name:String, title:String = "", complete:Function = null,
                                    flush:Boolean = false, showLoaderBar:Boolean = false,
                                    progress:Function = null, error:Function = null):void
        {
            var loaderItem:LoaderItem = LoaderMax.getLoader(name);

            if (!loaderItem)
            {
                loaderItem = LoaderMax.createLoader(name);
                if (!loaderItem)
                {
                    throw new Error("加载器名称不合法,loaderName=" + name);
                    return;
                }
            }

            if (loaderItem.loaderStatus == LoaderStatus.FAILED)
                loaderItem.loaderStatus = LoaderStatus.READY;

            //检查字典中的数组是否存在
            if (!_errorCallFunctionDic[name])
                _errorCallFunctionDic[name] = [];
            if (!_progressCallFunctionDic[name])
                _progressCallFunctionDic[name] = [];
            if (!_completeCallFunctionDic[name])
                _completeCallFunctionDic[name] = [];

            //保存回调方法
            if (error != null)
                _errorCallFunctionDic[name].push(error);
            if (progress != null)
                _progressCallFunctionDic[name].push(progress);
            if (complete != null)
                _completeCallFunctionDic[name].push(complete);

            _showLoaderBarDic[name] = showLoaderBar;

            //已经加载完成
            if (loaderItem.loaderStatus == LoaderStatus.COMPLETED && !flush)
            {
                cleanDic(name);

                if (complete != null)
                {
                    if (loaderItem is LoaderMax)
                    {
                        var loaderMax:LoaderMax = loaderItem as LoaderMax;
                        complete(new LoaderEvent(LoaderEvent.COMPLETE, loaderItem, loaderItem.bytesLoaded, loaderItem.bytesTotal, loaderMax.loadrCount, loaderMax.loaderTotalCount));
                    }
                    else
                        complete(new LoaderEvent(LoaderEvent.COMPLETE, loaderItem, loaderItem.bytesLoaded, loaderItem.bytesTotal));
                }
            }
            else if (loaderItem.loaderStatus != LoaderStatus.LOADING || flush)
            {
                //未加载时
                if (loaderItem.loaderStatus == LoaderStatus.READY || loaderItem.loaderStatus == LoaderStatus.COMPLETED)
                    addListener(loaderItem);

                //显示加载进度条
                if (faced && showLoaderBar)
                    faced.sendNotification(SHOW_LOADER_BAR_NOTE);

                //设置加载标题
                faced.sendNotification(SET_LOADER_BAR_TITLE_NOTE, title);

                loaderItem.load(flush);
            }
            else
            {
                //正在加载时
                if (!_hasAddListenerDic[name])
                    addListener(loaderItem);
            }
        }

        protected static function addListener(loaderItem:LoaderItem):void
        {
            _hasAddListenerDic[loaderItem.name] = true;

            loaderItem.addEventListener(LoaderEvent.COMPLETE, completeHandler);
            loaderItem.addEventListener(LoaderEvent.IO_ERROR, errorHandler);
            loaderItem.addEventListener(LoaderEvent.PROGRESS, progressHandler);
        }

        /**
         *加载完成
         *
         * @param event
         *
         */
        private static function completeHandler(event:LoaderEvent):void
        {
            var loaderItem:LoaderItem = event.currentLoader;

            var name:String = getLoaderName(loaderItem);

            removeListener(loaderItem);

            //发送隐藏进度条消息
            if (faced && _showLoaderBarDic[name])
                faced.sendNotification(HIDE_LOADER_BAR_NOTE);

            //执行方法回调
            for each (var completeFunciont:Function in _completeCallFunctionDic[name])
            {
                completeFunciont(event);
            }

            cleanDic(name);
        }

        /**
         *加载进度
         * @param event
         *
         */
        private static function progressHandler(event:LoaderEvent):void
        {
            var loaderItem:LoaderItem = LoaderItem(event.currentTarget);

            var name:String = getLoaderName(loaderItem);

            //执行方法回调
            for each (var progressFunciont:Function in _progressCallFunctionDic[name])
            {
                progressFunciont(event);
            }

            //发送更新加载进度消息
            if (faced && _showLoaderBarDic[name])
            {
                faced.sendNotification(SET_LOADER_BAR_PROGRESS_NOTE, event);
            }
        }

        /**
         *加载错误
         * @param event
         *
         */
        private static function errorHandler(event:LoaderEvent):void
        {
            var loaderItem:LoaderItem = LoaderItem(event.currentTarget);

            var name:String = getLoaderName(loaderItem);

            removeListener(loaderItem);

            //执行方法回调
            for each (var errorFunciont:Function in _errorCallFunctionDic[name])
            {
                errorFunciont(event);
            }

            //发送隐藏进度条消息
            if (faced && _showLoaderBarDic[name])
			{
                faced.sendNotification(HIDE_LOADER_BAR_NOTE);
				faced.sendNotification(LOADER_ERROR_NOTE);
			}
			
            cleanDic(name);
        }

        /**
         *移除监听
         * @param loaderCore
         *
         */
        private static function removeListener(loaderItem:LoaderItem):void
        {
            loaderItem.removeEventListener(LoaderEvent.COMPLETE, completeHandler);
            loaderItem.removeEventListener(LoaderEvent.IO_ERROR, errorHandler);
            loaderItem.removeEventListener(LoaderEvent.PROGRESS, progressHandler);
        }

        /**
         *清理回调方法字典
         * @param name
         *
         */
        private static function cleanDic(name:String):void
        {
            delete _completeCallFunctionDic[name];
            delete _progressCallFunctionDic[name];
            delete _errorCallFunctionDic[name];
            delete _showLoaderBarDic[name];
            delete _hasAddListenerDic[name];
        }

        protected static function getLoaderName(loaderItem:LoaderItem):String
        {
            var name:String = "";
            if (_completeCallFunctionDic[loaderItem.name])
                name = loaderItem.name;
            else if (_completeCallFunctionDic[loaderItem.url])
                name = loaderItem.url;

            return name;
        }
    }
}
